package com.atguigu.edu2021.mock.service.impl;


import com.atguigu.edu2021.mock.bean.OrderInfo;
import com.atguigu.edu2021.mock.config.AppConfig;
import com.atguigu.edu2021.mock.config.EduConstant;
import com.atguigu.edu2021.mock.service.OrderInfoService;
import com.atguigu.edu2021.mock.service.adv.impl.AdvServiceImpl;
import com.atguigu.edu2021.mock.bean.UserInfo;
import com.atguigu.edu2021.mock.mapper.UserInfoMapper;
import com.atguigu.edu2021.mock.service.UserInfoService;
import com.atguigu.mock.util.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author zc
 * @since 2020-02-23
 */
@Service
@Slf4j
public class UserInfoServiceImpl extends AdvServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    UserInfoMapper userInfoMapper;







     Set<Long> hasCourseUserSet;

    RandomBox<Boolean> ifStudyBox;


    @Autowired
     OrderInfoService orderInfoService;

    @PostConstruct
    protected void loadCache(){
        cache=new ConcurrentHashMap<>();
        resetUser();

        List<UserInfo> list = list(null);
        loadCache(  list);
        initHasCourseUserSet();
        ifStudyBox=new RandomBox<>(AppConfig.if_study, 100 - AppConfig.if_study);


    }

    protected  void resetUser(){
        boolean ifCleanUser=false;
        if( AppConfig.mock_clear_user.equals("1")){
            ifCleanUser=true;
        }
        genUserInfos(ifCleanUser,AppConfig.mock_new_user,AppConfig.mock_date);
    }

    protected  void initHasCourseUserSet(){
        List<OrderInfo> list = orderInfoService.list(new QueryWrapper<OrderInfo>().select("distinct user_id").eq("order_status", EduConstant.ORDER_STATUS_PAID));
        hasCourseUserSet = new CopyOnWriteArraySet<>();
        for (OrderInfo orderInfo : list) {
            hasCourseUserSet.add(orderInfo.getUserId());
        }
    }

    public boolean checkifStudy(Long userId){
        if(checkHasCourseByUserId(  userId))  {
           log.debug("userID："+userId+"有课程 可以学习 ");
            Boolean randBoolValue = ifStudyBox.getRandBoolValue();
            log.debug("userID："+userId+" 是否坚持 学习 "+randBoolValue);
            return randBoolValue ;
        }
        log.debug("userID："+userId+"无课程 无法学习 ");
        return  false;
    }

    public  boolean checkHasCourseByUserId(Long userId){
       return   hasCourseUserSet.contains(userId);
    }

    public void  genUserInfos( Boolean ifClear, Integer newUser, Date busiDate){



        List<UserInfo>  userInfoList=new ArrayList<>();
        if(ifClear){
            userInfoMapper.truncateUserInfo();
        }else{
            updateUsers(  busiDate);
        }

        for (int i = 0; i < newUser; i++) {
            userInfoList.add( initUserInfo(busiDate)) ;
        }
        if(userInfoList.size()>0){
            saveOrUpdateBatch(userInfoList,1000,true);
            fixUserInfo(  userInfoList);
            saveOrUpdateBatch(userInfoList,1000,true);
        }
        log.warn("共生成{}名用户",userInfoList.size());


    }

    public UserInfo initUserInfo(Date date){
       // Integer maleRateWeight = ParamUtil.checkRatioNum(this.maleRate);

        UserInfo userInfo = new UserInfo();
        String email = RandomEmail.getEmail(6, 12);
        String loginName = email.split("@")[0];
        userInfo.setLoginName(loginName);
        userInfo.setEmail(email);
           userInfo.setBirthday(DateUtils.addMonths(date, -1* RandomNum.getRandInt(15*12,55*12)));

        userInfo.setCreateTime(date);
        userInfo.setUserLevel(new RandomBox(new RanOpt("1",7),new RanOpt("2",2),new RanOpt("3",1)).getRandStringValue());
        userInfo.setPhoneNum("13"+RandomNumString.getRandNumString(1,9,9,""));
        return userInfo;
    }

    public void fixUserInfo(List<UserInfo> userInfoList){
        for (UserInfo userInfo : userInfoList) {
            String gender="";
            if(userInfo.getId()%2==0){
                gender="F";
            }else{
                gender="M";
            }
            if(userInfo.getId()%3!=0){
                userInfo.setGender(gender);
            }
            String lastName = RandomName.insideLastName(gender);
            userInfo.setRealName(RandomName.getChineseFamilyName()+lastName);
            userInfo.setNickName(RandomName.getNickName(gender,lastName));
        }

    }

    public void  updateUsers(Date date){


        Integer updateRateWeight = AppConfig.mock_user_update_rate ;

        int count = count(null);

        if(count==0){
            return;
        }
        String userIds = RandomNumString.getRandNumString(1, count, count *  updateRateWeight/ 100, ",",false);

        List<UserInfo> userInfoList = list(new QueryWrapper<UserInfo>().inSql("id", userIds));
        for (UserInfo userInfo : userInfoList) {
            int randInt = RandomNum.getRandInt(2, 7);
            String gender="";
            if(userInfo.getId()%2==0){
                gender="F";
            }else{
                gender="M";
            }
            if (randInt%2==0){
                String lastName = RandomName.insideLastName(gender);
                userInfo.setNickName(RandomName.getNickName(gender,lastName));
            }
            if(randInt%3==0){
                userInfo.setUserLevel(new RandomBox(new RanOpt("1",7),new RanOpt("2",2),new RanOpt("3",1)).getRandStringValue());
            }
            if(randInt%5==0){
                String email = RandomEmail.getEmail(6, 12);
                userInfo.setEmail(email);
            }
            if(randInt%7==0){
                userInfo.setPhoneNum("13"+RandomNumString.getRandNumString(1,9,9,""));
            }
            userInfo.setOperateTime(date);
        }
        log.warn("共有{}名用户发生变更",userInfoList.size());
        saveOrUpdateBatch(userInfoList,1000,true);



    }


    public void  setUserHasCourse(Long userId){
        hasCourseUserSet.add(userId);
    }


    public void clearUserHasCourse(){
        hasCourseUserSet.clear();
    }
}
